//
//  Block.swift
//  Z048
//
//  Created by remy on 2020/1/31.
//  Copyright © 2020 remy. All rights reserved.
//

//protocol BaseBlock {
//    var index: Int { get set }
//    var level: Int { get set }
//    var maxLevel: Int { get }
//}

struct BlockAction {
    static let create: SKAction = {
        let wait = SKAction.wait(forDuration: 0.15)
        let fade = SKAction.fadeIn(withDuration: 0.0)
        let scale = SKAction.scale(to: 1.0, duration: 0.2)
        scale.timingMode = .easeIn
        return SKAction.sequence([wait, fade, scale])
    }()
    static let levelChanged: SKAction = {
        let wait = SKAction.wait(forDuration: 0.15)
        let scale1 = SKAction.scale(to: 1.2, duration: 0.1)
        scale1.timingMode = .easeIn
        let scale2 = SKAction.scale(to: 1.0, duration: 0.1)
        scale2.timingMode = .easeIn
        return SKAction.sequence([wait, scale1, scale2])
    }()
    static let maxDuration: SKAction = SKAction.wait(forDuration: 0.36)
    static func move(_ point: CGPoint) -> SKAction {
        let move = SKAction.move(to: point, duration: 0.15)
        move.timingMode = .easeIn
        return move
    }
    static func mix(_ point: CGPoint, _ wait: TimeInterval = 0.0) -> SKAction {
        return SKAction.sequence([move(point), SKAction.wait(forDuration: wait), SKAction.removeFromParent()])
    }
}

class Block {
    private(set) var index: Int = 0
    private(set) var level: Int = 0
    private(set) var maxLevel: Int = 0
    
    init(index: Int, level: Int, maxLevel: Int) {
        self.index = index
        self.level = level
        self.maxLevel = maxLevel
    }
    
    func moveTo(_ index: Int) {
        self.index = index
    }
    
    func levelTo(_ level: Int) {
        guard self.level != level else { return }
        guard level >= 0, level <= maxLevel else { return }
        self.level = level
    }
    
    func levelUp() {
        levelTo(level + 1)
    }
    
    func levelDown() {
        levelTo(level - 1)
    }
    
    deinit {
        Risac.print("Block kill ------> Index: \(index), Level: \(level)/\(maxLevel)")
    }
}

class PlainBlock: Block {
    lazy var colors: [Int] = [0xFFEB3B, 0xFFC107, 0xFF9800, 0xFF5722, 0xCDDC39, 0x8BC34A, 0x4CAF50, 0x009688, 0x00BCD4, 0x03A9F4, 0x2196F3, 0x3F51B5, 0x673AB7, 0x9C27B0, 0x880E4F, 0xb71c1c]
    lazy var node: (SKShapeNode, SKLabelNode, SKLabelNode) = {
        let node = SKShapeNode(rectOf: Constants.blockSize, cornerRadius: 6.0)
        node.strokeColor = .clear
        let label = SKLabelNode(fontNamed: "AvenirNext-Medium")
        label.verticalAlignmentMode = .center
        label.fontSize = node.frame.size.height * 0.4
        label.fontColor = .white
        node.addChild(label)
        let power = SKLabelNode(fontNamed: "AvenirNext-Medium")
        power.horizontalAlignmentMode = .left
        power.verticalAlignmentMode = .bottom
        power.fontSize = node.frame.size.height * 0.2
        power.fontColor = .white
        power.position = CGPoint(x: node.frame.size.width * 0.12, y: node.frame.size.height * 0.15)
        node.addChild(power)
        return (node, label, power)
    }()
    
    init(index: Int) {
        super.init(index: index, level: 0, maxLevel: 15)
    }
    
    func addTo(_ superNode: SKNode) {
        node.0.zPosition = 10.0
        node.0.alpha = 0.0
        node.0.setScale(0.8)
        node.0.fillColor = UIColor(colors[level % colors.count])
        node.0.position = Constants.points[index]
        node.0.run(BlockAction.create)
        updateText()
        superNode.addChild(node.0)
    }
    
    override func moveTo(_ index: Int) {
        super.moveTo(index)
        node.0.run(BlockAction.move(Constants.points[index]))
    }
    
    func mixTo(_ index: Int) {
        super.moveTo(index)
        node.0.run(BlockAction.mix(Constants.points[index]))
    }
    
    override func levelTo(_ level: Int) {
        super.levelTo(level)
        node.0.fillColor = UIColor(colors[level % colors.count])
        node.0.run(BlockAction.levelChanged)
        updateText()
    }
    
    func updateText() {
        if level > 12 {
            node.1.text = "2"
            node.2.text = "\(level + 1)"
        } else {
            node.1.text = "\(pow(2.0, level + 1))"
            node.2.text = nil
        }
    }
}
